/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hoja.de.trabajo.pkg6;

/**
 *
 * @author FRANCISCO
 */
import java.util.Iterator;

public class SinglyLinkedList <E> implements List <E>, Iterable <E> {
    
            /* ATRIBUTOS DE LA CLASE SINGLY LINKED LIST */
    
            protected int count;                                                // TAMAÑO DE LA LISTA
            protected Node<E> head;                                             // REFERENCIA AL PRIMER ELEMENTO
            protected Node<E> current;

            
            /**
             * Constructor de la clase Singly Linked List, crea una nueva lista
             * sin ningún elemento.
             */
            public SinglyLinkedList() {
                head = null;
                count = 0;
            }
            
            
            /**
             * Método que permite conocer el número de elementos en la lista.
             * @return número int de elementos en la lista.
             */
            public int size() {
                return count;
            }
            
            
            /**
             * Método que permite añadir un elemento al inicio de la lista.
             * @param value 
             */
            public void addFirst(E value) {
                head = new Node<E>(value,head);
                count++;
            }

            
            /**
             * Método que permite remover el primer elemento de la lista
             * con el valor determinado.
             * @param value
             * @return 
             */
            public E remove(E value) {
                Node<E> finger = head;
                Node<E> previous = null;
                while (finger != null && !finger.value().equals(value)) {
                    previous = finger;
                    finger = finger.next();
                }
                if (finger != null) {
                    if (previous == null) {
                        head = finger.next();
                    } else  {
                        previous.setNext(finger.next());
                    } 
                    count--;
                    return finger.value();
                }
                return null;
            }
            
            
            /**
             * Método que permite obtener el primer elemento de la lista.
             * @return primer elemento E de la lista.
             */
            public E getFirst() {
                return head.value();
            }


            /**
             * Método que permite añadir un valor al último elemento de la
             * lista.
             * @param value 
             */
            public void addLast(E value) {
                Node<E> temp = new Node<E>(value,null);
                if(head != null) {
                    Node<E> finger = head;
                    while (finger.next() != null) {
                        finger = finger.next();
                    }
                    finger.setNext(temp);
                } else head = temp;
                count++;
            }

            
            /**
             * Método que permite obtener un iterador de la lista.
             * @return iterador E de la lista.
             */
            public Iterator <E> iterator() {
                return new SiglyLinkedListIterator();
            }


            /**
             * Clase que permite la implementación de un iterador a la lista
             * simplemente encadenada.
             */
            private class SiglyLinkedListIterator implements Iterator<E> {
                
                /* ATRIBUTOS DE LA CLASE */
                
                protected Node<E> current;

                
                /* MÉTODOS DE LA CLASE */
                
                
                /**
                 * Constructor de la clase SinglyLinkedListIterator, define la
                 * referencia del iterador.
                 */
                public SiglyLinkedListIterator() {
                    current = head;
                }

                
                /**
                 * Método que permite reiniciar la referencia del iterador de 
                 * la lista. 
                 */
                public void reset() {
                    current = head;
                }

                
                /**
                 * Método que permite conocer si existe otra estrcutura a 
                 * estudiar.
                 * @return true si existe una estructura.
                 */
                public boolean hasNext() {
                    return current != null;
                }

                /**
                 * Método que obtiene el valor actual e incrementa el iterador.
                 * @return valor E actual
                 */
                public E next() {
                    E temp = current.value();
                    current = current.next();
                    return temp;
                }

                public void remove() {}
            }   
           
}   // FIN DE LA CLASE SINGLY LINKED LIST
